<?php
 namespace app\models;
 
 /**
  * @desc 拆装单
  */
 use app\models\BaseModel;
 use Yii;
 use app\enum\EnumOther;
 use app\dao\DisassemblyDAO;
 use app\dao\DisassemblyDetailDAO;
 use app\enum\EnumOriginType;
 use app\dao\GoodsQuantityDAO;
 use app\dao\TransactionDAO;
 use app\dao\ProductUpdateLogDAO;
 use app\dao\StockPileDAO;
 use app\dao\WarehouseDAO;
 use app\helpers\Utility;
use app\dao\ProductDAO;
	
			 
 class DisassemblyModel extends BaseModel 
 {
 	/**
 	 * @desc 初始化对象
 	 * @author liaojianwen
 	 * @date 2017-10-17
 	 * @return DisassemblyModel
 	 */
 	public static function model($className = __CLASS__)
 	{
 		return parent::model($className);
 	}
 	
 	/**
 	 * @desc 保存拆装单
 	 * @author liaojianwen
 	 * @date 2017-10-17
 	 */
 	public function saveDisassembly($head, $detail, $remove, $id)
 	{
 		if(empty($head)){
 			return $this->handleApiFormat ( EnumOther::ACK_FAILURE, '', 'head is empty' );
 		}
 		if (empty ( $detail )) {
 			return $this->handleApiFormat ( EnumOther::ACK_FAILURE, '', 'detail is empty' );
 		}
 		//清掉为空的元素
 		foreach ($head as $k =>$hed){
 			if(empty($hed)){
 				unset($head[$k]);
 			}
 		}
 		foreach ($detail as $k=> $det){
 			foreach ($det as $j => $deet){
 				if(empty($deet)){
 					unset($detail[$k][$j]);
 				}
 			}
 		}
 		// 表头信息
 		$tr = Yii::$app->db->beginTransaction();
 		try{
 			$head ['disassembly_date'] = strtotime ( $head ['disassembly_date'] );
 			$cond_head = "disassembly_id =:id";
 			$param_head = [
 					':id' => $id
 			];
 			//  			$Iid = 1;
 			$Iid = DisassemblyDAO::getInstance ()->ireplaceinto ( $head, $cond_head, $param_head, true );
 			if (! $Iid) {
 				$tr->rollBack();
 				return $this->handleApiFormat ( EnumOther::ACK_FAILURE, '', 'save disassembly_head failure' );
 			}
 			//删除的明细
 			foreach ($remove as $move){
 				$res_remove = DisassemblyDetailDAO::getInstance()->iupdate(['delete_flag'=>EnumOther::DELETED], "disassembly_det_id = :det_id", [':det_id'=>$move['disassembly_det_id']]);
 				if(!$res_remove){
 					$tr->rollBack();
 					$this->handleApiFormat(EnumOther::ACK_FAILURE, '', 'remove disassembly_dat_id:'+$move['disassembly_det_id'] +'failed');
 				}
 			}
 			foreach ( $detail as &$det ) {
 				$det ['disassembly_id'] = $Iid;
 				//  				$det ['delete_flag'] = EnumOther::NO_DELETE;
 				$cond_det = "disassembly_id = :id and disassembly_det_id = :lid";
 				$param_det = [
 						':id' => $Iid,
 						':lid' => isset($det ['disassembly_det_id'])?$det['disassembly_det_id']:0,
 				];
 				$res_det = DisassemblyDetailDAO::getInstance ()->ireplaceinto ( $det, $cond_det, $param_det, true );
 				if (! $res_det) {
 					$tr->rollBack();
 					return $this->handleApiFormat ( EnumOther::ACK_FAILURE, '', 'save disassembly_detail failure' );
 				}
 			}
 			$tr->commit();
 			return $this->handleApiFormat ( EnumOther::ACK_SUCCESS, '' );
 		}catch (\Exception $e){
 			$tr->rollBack();
 			return $this->handleApiFormat(EnumOther::ACK_FAILURE, '', $e->getMessage());
 		}
 		
 	}
 	
 	/**
 	 * @desc 获取拆卸单列表
 	 * @author liaojianwen
 	 * @date 2017-10-19
 	 */
 	public function getDisassembly ( $pageInfo, $condition, $filter)
 	{
 		if(empty($pageInfo)){
 			return $this->handleApiFormat(EnumOther::ACK_FAILURE,'','param is empty');
 		}
 		$result = DisassemblyDAO::getInstance()->getDisassembly($condition, $filter, $pageInfo);
 		if(empty($result)){
 			return $this->handleApiFormat(EnumOther::ACK_FAILURE,'','no data found');
 		}
 		return $this->handleApiFormat(EnumOther::ACK_SUCCESS,$result);
 	}
 	
 	/**
 	 * @desc 编辑页面的明细
 	 * @author liaojianwen
 	 * @date 2017-10-19
 	 */
 	public function getDisassemblyInfo($id)
 	{
 		if(empty($id)){
 			return $this->handleApiFormat(EnumOther::ACK_FAILURE,'','param is empty');
 		}
 		$in_head = DisassemblyDAO::getInstance()->getDisassemblyHead($id);
 		if(empty($in_head)){
 			return $this->handleApiFormat(EnumOther::ACK_FAILURE,'','head data found');
 		}
 		$in_det = DisassemblyDetailDAO::getInstance()->getDisassemblyDetail($id);
 		if(empty($in_det)){
 			return $this->handleApiFormat(EnumOther::ACK_FAILURE,'','detail data found');
 		}
 		$result['head'] = $in_head;
 		$result['det'] = $in_det;
 		return $this->handleApiFormat(EnumOther::ACK_SUCCESS,$result);
 	}
 	
 	/**
 	 * @desc 确认拆装单
 	 * @author liaojianwen
 	 * @date 2017-10-19
 	 */
 	public function confirmDisassembly($id)
 	{
 		if (! $id) {
 			return $this->handleApiFormat ( EnumOther::ACK_FAILURE, '', 'param is empty' );
 		}
 		$id = (int)$id;
 		$tr = Yii::$app->db->beginTransaction ();
 		try {
 			$re_confirm = DisassemblyDAO::getInstance ()->updateByPk ( $id, [
 					'confirm_flag' => EnumOther::CONFIRM
 			] );
 			if (! $re_confirm) {
 				$tr->rollBack ();
 				return $this->handleApiFormat ( EnumOther::ACK_FAILURE, '', 'confirm fail' );
 			}
 			$fields = [
 					'h.disassembly_no',
 					'd.product_id',
 					'd.quantity',
 					'd.disassembly_det_id',
 					'h.warehouse_out',
 					'h.warehouse_in',
 					'h.disassembly_date',
 					'd.quantity_unit',
 					'd.base_quantity',
 					'd.base_unit',
 					'w.warehouse_name as warehouse_in_name',
 					'd.type'
 			];
 			$conditions = "d.disassembly_id =:id and d.delete_flag = :flag";
 			$params = [
 					':id' => $id,
 					':flag' => EnumOther::NO_DELETE
 			];
 			$joinArray = [
 					[
 							'disassembly h',
 							"h.disassembly_id = d.disassembly_id"
 					],
 					[
 							'warehouse w',
 							'w.warehouse_id = h.warehouse_in',
 					]
 			];
 			$disassembly_det = DisassemblyDetailDAO::getInstance ()->iselect ( $fields, $conditions, $params, 'all', 'd.disassembly_det_id ASC', $joinArray, 'd' );
 			if (! $disassembly_det) {
 				$tr->rollBack ();
 				return $this->handleApiFormat ( EnumOther::ACK_FAILURE, '', 'select det fail' );
 			}
 		
 			// 明细
 			foreach ( $disassembly_det as $det ) {
 				$column_trans = [];
 				$Type = $det['type'];
 				$PRODUCT = ProductDAO::getInstance()->iselect(['quantity'], "product_id =:gid", [':gid'=>$det['product_id']],'one');
 				if($Type){
	 				//in 入库时报废仓
	 				$WAREHOUSE = WarehouseDAO::getInstance()->iselect("is_scrapped,warehouse_name", "warehouse_id =:wid", [':wid'=>$det['warehouse_in']],'one');
	 				// 更新goods quantity 
	 				if(isset($WAREHOUSE['is_scrapped'])){
	 					if($WAREHOUSE['is_scrapped'] == '1'){//报废仓
							//报废仓不计库存
	 					} else {
	 						$pro_select = ProductDAO::getInstance ()->updateAllCounters ( [
									'quantity' => $det ['base_quantity'] 
							], "product_id = :gid", [ 
									":gid" => $det ['product_id'],
							] );
							if (! $pro_select) {
								$tr->rollBack ();
								return $this->handleApiFormat ( EnumOther::ACK_FAILURE, '', 'update product quantity failure' );
	 						}
	 					}
	 				} else {
	 					$tr->rollBack();
	 					return $this->handleApiFormat(EnumOther::ACK_FAILURE,'','select scrapped failed');
	 				}
 				} else {
	 				//出库是报废仓，加上quantity
	 				$warehouse_out = WarehouseDAO::getInstance()->iselect("is_scrapped,warehouse_name", "warehouse_id =:wid", [':wid'=>$det['warehouse_out']],'one');
	 				if(isset($warehouse_out['is_scrapped'])){
	 					if($warehouse_out['is_scrapped'] == '1'){
	 						//不改变goods_quantity
	 					} else {
	 						if($det['base_quantity'] > $PRODUCT['quantity']){
	 							$tr->rollBack();
	 							return $this->handleApiFormat(EnumOther::ACK_FAILURE, '', 'out_quantity lt base_quantity');
	 						} else {
		 						$pro_select = ProductDAO::getInstance ()->updateAllCounters ( [
		 								'quantity' => -$det ['base_quantity']
		 						], "product_id = :gid", [
		 								":gid" => $det ['product_id'],
		 						] );
		 						if (! $pro_select) {
		 							$tr->rollBack ();
		 							return $this->handleApiFormat ( EnumOther::ACK_FAILURE, '', 'update product quantity failure' );
		 						}
	 						}
	 					}
	 				} else {
	 					$tr->rollBack();
	 					return  $this->handleApiFormat(EnumOther::ACK_FAILURE,'','select scrapped failed');
	 				}
 				}
 				$column_trans = [
 						[
 								'goods_id' => $det ['product_id'],
 								'quantity' => $det ['base_quantity'],
 								'quantity_unit' => $det ['base_unit'],
 								'origin_type' => EnumOriginType::origin_disassembly,
 								'origin_id' => $det ['disassembly_no'],
 								'origin_line_id' => $det ['disassembly_det_id'], // 原单序号
 								'origin_time' => $det ['disassembly_date'],
 								'warehouse_id' => $Type ? $det['warehouse_in']:$det ['warehouse_out'],//仓库
 								'init_num' => $PRODUCT['quantity'],
 								'flag' => $Type ? EnumOther::IN_FLAG : EnumOther::OUT_FLAG,
 						],
 				];
 					
 				foreach ($column_trans as $trans){
 					$res_trans = TransactionDAO::getInstance ()->iinsert ($trans, true );
 					if (! $res_trans) {
 						$tr->rollBack ();
 						return $this->handleApiFormat ( EnumOther::ACK_FAILURE, '', 'save transaction failure' );
 					}
 				}
 					
 		
 				//
 				//product_update_log 商品更新记录
 				$_order_type = Utility::getArrayValue(EnumOriginType::$origin_type,EnumOriginType::origin_disassembly);
 				$log_columns = [
 						[
 								'product_id' => $det ['product_id'],
 								'update_num' => $det ['base_quantity'],
 								'num_unit' => $det ['base_unit'],
 								'origin_id' => $id,
 								'origin_no' => $det['disassembly_no'],
 								'origin_line_id' => $det ['disassembly_det_id'],
 								'origin_type' => EnumOriginType::origin_disassembly,
 								'update_time' => strtotime ( date ( 'Y-m-d' ) ),
 								'flag' => $Type ? EnumOther::IN_FLAG : EnumOther::OUT_FLAG,
 								'initial_num' => $PRODUCT ['quantity'], // 上期数量
 								'remark' => $Type ? ($_order_type . $WAREHOUSE['warehouse_name'].EnumOther::PLUS) : ($_order_type . $warehouse_out['warehouse_name']. EnumOther::MINUS),
 								'warehouse_id'=> $Type ? $det['warehouse_in']:$det ['warehouse_out'],
 								'create_man' => Yii::$app->user->id,
 						],
 							
 				];
 		
 				foreach ($log_columns as $logs){
 					$res_log = ProductUpdateLogDAO::getInstance()->iinsert($logs, true);
 					if(! $res_log){
 						$tr->rollBack();
 						return $this->handleApiFormat(EnumOther::ACK_FAILURE, '', 'product update log failure');
 					}
 				}
 					
 				//分仓列表数据的插入或者更新--start
 				
 				if($Type){
 					//入库
 					$stockin_conditions = "warehouse_id =:wid and product_id=:pid and delete_flag =:flag";
 					$stockin_params = [
 							':wid'=>$det['warehouse_in'],
 							':pid'=>$det['product_id'],
 							':flag'=> EnumOther::NO_DELETE,
 					];
 					$stockin_select = StockPileDAO::getInstance()->iselect("stock_pile_id", $stockin_conditions, $stockin_params,'one');
 					if(! $stockin_select){
 						// 没有数据，插入新数据
 						$stockin_columns = [
 								'warehouse_id'=> $det['warehouse_in'],
 								'product_id'=> $det['product_id'],
 								'quantity'=> $det['base_quantity'],
 								'quantity_unit'=> $det['base_unit'],
 						];
 						$stockin_insert = StockPileDAO::getInstance()->iinsert($stockin_columns, true);
 						if(! $stockin_insert){
 							$tr->rollBack ();
 							return $this->handleApiFormat ( EnumOther::ACK_FAILURE, '', 'insert stock pile failure' );
 						}
 							
 					} else {
 						//有数据，更新数据
 						$stockin_update = StockPileDAO::getInstance()->updateAllCounters(['quantity'=> $det['base_quantity']], $stockin_conditions, $stockin_params);
 						if(! $stockin_update){
 							$tr->rollBack();
 							return $this->handleApiFormat(EnumOther::ACK_FAILURE, '','update stock pile failure');
 						}
 					}
 				} else {
 					//出库
	 				$stockout_conditions = "warehouse_id =:wid and product_id=:pid and delete_flag =:flag";
	 				$stockout_params = [
	 						':wid'=>$det['warehouse_out'],
	 						':pid'=>$det['product_id'],
	 						':flag'=> EnumOther::NO_DELETE,
	 				];
	 				$stockout_select = StockPileDAO::getInstance()->iselect("stock_pile_id", $stockout_conditions, $stockout_params,'one');
	 				if(! $stockout_select){
	 					$tr->rollBack ();
	 					return $this->handleApiFormat ( EnumOther::ACK_FAILURE, '', 'select stock pile failure' );
	 				} else {
	 					//有数据，更新数据
	 					$stockout_update = StockPileDAO::getInstance()->updateAllCounters(['quantity'=> -$det['base_quantity']], $stockout_conditions, $stockout_params);
	 					if(! $stockout_update){
	 						$tr->rollBack();
	 						return $this->handleApiFormat(EnumOther::ACK_FAILURE, '','update stock pile failure');
	 					}
	 				}
 				}
 				//分仓 --end
 		
 			}
 			$tr->commit();
 			return $this->handleApiFormat(EnumOther::ACK_SUCCESS,'');
 		} catch ( \Exception $e ) {
 			$tr->rollBack ();
 			return $this->handleApiFormat(EnumOther::ACK_FAILURE,'',$e->getMessage());
 		}
 	}
 	
 	
 	/**
 	 * @desc 删除拆装单
 	 * @param $ids string // 1,2,3,4
 	 * @author liaojianwen
 	 * @date 2017-10-20
 	 */
 	public function delDisassembly($ids)
 	{
 		if(empty($ids)){
 			return $this->handleApiFormat ( EnumOther::ACK_FAILURE, '', 'param is empty' );
 		}
 		$_ids = explode ( ',', $ids );
 	
 		$tT = Yii::$app->db->beginTransaction ();
 		try {
 			foreach ( $_ids as $id ) {
 				$res_disassembly = DisassemblyDAO::getInstance ()->updateByPk ( $id, ['delete_flag' => EnumOther::DELETED] );
 				if(!$res_disassembly){
 					$tT->rollBack();
 					return $this->handleApiFormat(EnumOther::ACK_FAILURE, '', 'del_disassembly fail');
 				}
 				//disassembly_detail
 				$disassembly_det = DisassemblyDetailDAO::getInstance()->iupdate(['delete_flag'=>EnumOther::DELETED], "disassembly_id=:id", [':id'=>$id]);
 				if(!$disassembly_det){
 					$tT->rollBack();
 					return $this->handleApiFormat(EnumOther::ACK_FAILURE,'','del_disassembly_det fail');
 				}
 				//更新product_quantity
 				$fields = [
 						't.goods_id',
 						't.quantity',
 						't.transaction_id',
 						'd.quantity_unit',
 						't.warehouse_id',
 						't.origin_id',
 						't.origin_type',
 						'd.quantity_unit',
 						'd.disassembly_det_id',
 						't.flag',
 				];
 				$conditions = "t.delete_flag = :flag";
 				$params = [
 						':flag'=>EnumOther::NO_DELETE,
 				];
 				$joinArray = [
 						[
 								'disassembly i',
 								'i.disassembly_no = t.origin_id and i.disassembly_id = '.$id,
 								'right'=>'',
 						],
 						[
 								'disassembly_detail d',
 								'd.disassembly_det_id = t.origin_line_id',
 								'left'=>''
 						]
 				];
 				$trans_select = TransactionDAO::getInstance()->iselect($fields, $conditions, $params,'all',"t.create_time ASC",$joinArray,'t');
 				if (! empty ( $trans_select )) {
 					// 已确认的入库单才有transtions,减库存
 					foreach ( $trans_select as $trans ) {
 						//记录更新product 前的quantity
 						$PRODUCT = ProductDAO::getInstance()->iselect("quantity", "product_id = :pid", [':pid'=>$trans['goods_id']],'one');
 						//product 更新数量
 						$_order_type = Utility::getArrayValue(EnumOriginType::$origin_type, $trans['origin_type']);
 						if($trans['flag']){
 							//transtion 是入库     删除即是减少库存
 							$WAREHOUSE = WarehouseDAO::getInstance()->iselect("is_scrapped,warehouse_name", "warehouse_id =:wid", [':wid'=>$trans['warehouse_id']],'one');
 							//如果入库的仓库是报废仓就不用操作
 							if($WAREHOUSE['is_scrapped'] == '0'){//非报废仓
 								$pro_minus = ProductDAO::getInstance ()->updateAllCounters ( [
 										'quantity' => - $trans ['quantity'],
 								], "product_id =:id", [
 										':id' => $trans ['goods_id'],
 								] );
 								 
 								if (! $pro_minus) {
 									$tr->rollBack ();
 									return $this->handleApiFormat ( EnumOther::ACK_FAILURE, '', 'update product quantity failure' );
 								}
 							}
 							$log_columns = [
 									'product_id' => $trans ['goods_id'],
 									'update_num' => $trans ['quantity'],
 									'num_unit' => $trans ['quantity_unit'],
 									'origin_id' => $id,
 									'origin_no' => $trans['origin_id'],
 									'origin_line_id' => $trans ['disassembly_det_id'],
 									'origin_type' => $trans ['origin_type'],
 									'update_time' => strtotime ( date ( 'Y-m-d' ) ),
 									'flag' => EnumOther::OUT_FLAG,
 									'initial_num' => $PRODUCT ['quantity'], // 上期数量
 									'remark' => $_order_type.$WAREHOUSE['warehouse_name'] . EnumOther::MINUS . ',拆装单组合记录删除' ,
 									'warehouse_id' => $trans['warehouse_id'],
 									'create_man' => Yii::$app->user->id,
 							];
 	
 						} else {
 							$warehouse_out = WarehouseDAO::getInstance()->iselect("is_scrapped,warehouse_name", "warehouse_id =:wid", [':wid'=>$trans['warehouse_id']],'one');
 							if($warehouse_out['is_scrapped'] == '0'){//非报废仓,出库仓是报废仓不能更改goods_quantity
 								$pro_plus = ProductDAO::getInstance ()->updateAllCounters ( [
 										'quantity' => $trans ['quantity'],
 								], "product_id =:id", [
 										':id' => $trans ['goods_id'],
 								] );
 									
 								if (! $pro_plus) {
 									$tr->rollBack ();
 									return $this->handleApiFormat ( EnumOther::ACK_FAILURE, '', 'update product quantity failure' );
 								}
 							}
 							$log_columns = [
 									'product_id' => $trans ['goods_id'],
 									'update_num' => $trans ['quantity'],
 									'num_unit' => $trans ['quantity_unit'],
 									'origin_id' => $id,
 									'origin_no' => $trans['origin_id'],
 									'origin_line_id' => $trans ['disassembly_det_id'],
 									'origin_type' => $trans ['origin_type'],
 									'update_time' => strtotime ( date ( 'Y-m-d' ) ),
 									'flag' => EnumOther::IN_FLAG,
 									'initial_num' => $PRODUCT ['quantity'], // 上期数量
 									'remark' => $_order_type .$warehouse_out['warehouse_name']. EnumOther::PLUS . ',拆装单拆卸记录删除' ,
 									'warehouse_id' => $trans['warehouse_id'],
 									'create_man' => Yii::$app->user->id,
 							];
 						}
 						
 						$res_log = ProductUpdateLogDAO::getInstance()->iinsert($log_columns, true);
 						if(! $res_log){
 							$tr->rollBack();
 							return $this->handleApiFormat(EnumOther::ACK_FAILURE, '', 'product update log failure');
 						}
 	
 						//删除transaction 数据
 						$columns = [
 								'delete_flag'=>EnumOther::DELETED,
 						];
 						$conditions = "transaction_id = :tid";
 						$params = [
 								':tid'=>$trans['transaction_id'],
 						];
 						$trans_update = TransactionDAO::getInstance()->iupdate($columns, $conditions, $params);
 	
 						if(empty($trans_update)){
 							$tT->rollBack();
 							return $this->handleApiFormat(EnumOther::ACK_FAILURE,'','tansaction del fail');
 						}
 						// 更新stock_file 分仓表信息
 						if($trans['flag']){
 							//调入仓库  删除就要减去 quantity
 							$stock_minus = StockPileDAO::getInstance ()->updateAllCounters ( [
 									'quantity' => - $trans ['quantity']
 							], "warehouse_id =:wid and product_id=:pid and delete_flag =:flag", [
 									':wid' => $trans ['warehouse_id'],
 									':pid' => $trans ['goods_id'],
 									':flag' => EnumOther::NO_DELETE,
 							] );
 							if(! $stock_minus){
 								$tr->rollBack ();
 								return $this->handleApiFormat(EnumOther::ACK_FAILURE, '', 'update stock pile quantity failure');
 							}
 						} else {
 							$stock_plus = StockPileDAO::getInstance ()->updateAllCounters ( [
 									'quantity' => $trans ['quantity']
 							], "warehouse_id =:wid and product_id=:pid and delete_flag =:flag", [
 									':wid' => $trans ['warehouse_id'],
 									':pid' => $trans ['goods_id'],
 									':flag' => EnumOther::NO_DELETE,
 							] );
 							if(! $stock_plus){
 								$tr->rollBack ();
 								return $this->handleApiFormat(EnumOther::ACK_FAILURE, '', 'update stock pile quantity failure');
 							}
 						}
 					}
 				}
 			}
 				
 			$tT->commit();
 			return $this->handleApiFormat(EnumOther::ACK_SUCCESS,'');
 		} catch ( \Exception $e ) {
 			$tT->rollBack ();
 			return $this->handleApiFormat(EnumOther::ACK_FAILURE, '', $e->getMessage());
 		}
 	}
 	
 	
 	/**
 	 * @desc 根据仓库id获取仓库内的商品列表
 	 * @param $ware_id 仓库id
 	 * @param [] $name 查询条件
 	 * @param $pageInfo 页面信息
 	 * @author liaojianwen
 	 * @date 2017-11-21
 	 */
 	public function getDisassemblyProductByWare($ware_id, $name, $pageInfo)
 	{
		if (! $ware_id) {
			return $this->handleApiFormat ( EnumOther::ACK_FAILURE, '', 'warehouse_id is empty' );
		}
		$result = StockPileDAO::getInstance ()->getDisassemblyProductByWare ( $ware_id, $name, $pageInfo );
		if (empty ( $result )) {
			return $this->handleApiFormat ( EnumOther::ACK_FAILURE, '', 'no data found' );
		}
		return $this->handleApiFormat ( EnumOther::ACK_SUCCESS, $result );
 	}
 }
 